package A3GCConcreteTestCase;

import java.util.Iterator;

import org.jgroups.Address;
import org.jgroups.JChannel;
import org.jgroups.Message;

import A3GCPackage.SingleNodeData;
import A3JGroups.A3JGMessage;
import A3JGroupsGC.GCSupervisorRole;

public class ConcreteSupervisor extends GCSupervisorRole 
{

	public static boolean locations_operational_flag = false;
	
	public ConcreteSupervisor(int resourceCost, String groupName) 
	{
		super(resourceCost, groupName);
	}

	@Override
	public A3JGMessage translateMessage(A3JGMessage mex, SingleNodeData snd ) 
	{
		if ( mex == null )
			return null;
		
		//return mex;
		// waste of time, just resend entire message
		A3JGMessage out = new A3JGMessage();
		out.setType( false );
		String msg = mex.getContent().toString();
		msg = msg + "#" + snd.name;
		out.setContent(msg);
		
		System.out.println("ConcreteSupervisor[" + this.getNode().getID() + "," + getChan().getAddress().toString() + "]::translateMessage: sending a message to group <" + msg + ">" );
		
		return out;
	}

	@Override
	public String passMessageToClient(A3JGMessage mex) 
	{
		// this will go back to the location supervisor to give to the client
		System.out.println("ConcreteSupervisor[" + this.getNode().getID() + "," + getChan().getAddress().toString() + "]::passMessageToClient: got a message need to send back to the client <" + mex.getContent().toString() +  ">" );
		
		A3JGMessage out = new A3JGMessage();
		out.setType( true );
		String splits[] = mex.getContent().toString().split("#");
		String gn, num, client, orig, sender;
		if ( splits.length < 5 && locations_operational_flag )
			return null; // bad message
		
		gn     = splits[0];
		num    = splits[1];
		client = splits[2];
		orig   = splits[3];
		if ( locations_operational_flag )
			sender = splits[4];
		else
			sender = splits[3];
		
		String msg;
		msg = gn + "#" + num + "#" + client + "#" + orig;
		System.out.println("ConcreteSupervisor[" + this.getNode().getID() + "," + getChan().getAddress().toString() + "]::passMessageToClient: msg is <" + msg + "> and orig is <" + orig + ">" );
		System.out.println("Sender is <" + sender + ">");
		
		Address retaddr;
		JChannel chan;
		
		if ( locations_operational_flag )
		{
			retaddr = node.getSupervisorMap().get( orig );
			chan = node.getChannels(orig);
		}
		else
		{
			chan = getChan();
			retaddr = null;
			Iterator<Address> iter = view.getMembers().iterator();
			while ( iter.hasNext() )
			{
				Address addr = iter.next();
				
				if ( addr.toString().compareTo(client) == 0 )
				{
					retaddr = addr;
					break;
				}
			}
			if ( retaddr == null )
			{
				return sender;
			}
		}
		
		// send to the location supervisor
		msg = msg.substring(0, msg.lastIndexOf("#") );
		Message m = new Message();
		out.setContent( msg );
		m.setObject( out );
		m.setDest(retaddr);
		try 
		{
			chan.send( m );
		}
		catch (Exception e) 
		{
			e.printStackTrace();
		}
		
		return sender;
	}

	@Override
	public void run() 
	{
		// don't let this function end unless everything ends
		while ( this.active )
		{
			try
			{
				Thread.sleep(2000);
			}
			catch (Exception e)
			{
				
			}
		}
	}

	@Override
	public int fitnessFunc() 
	{
		return 0;
	}

	@Override
	public void noNodeAvailable(A3JGMessage mex) 
	{
		System.out.println("ConcreteSupervisor[" + this.getNode().getID() + "]: noNodeAvailable called." );
	}

}
